/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
 */
import * as execa from 'execa';
import os from 'os';
import { resolve } from 'path';
import * as fs from 'fs-extra';
import { Json5Reader } from '../../../../src/base/util/json5-reader';
import { hvigorCore } from '../../../../index';

hvigorCore.getProject();

const debugMode = false;

export type hvigorOptions = {
  mode?: string,
  module?: string | string[],
  log?: string,
  require?: string,
  v?: boolean
  version?: boolean,
  sync?: boolean,
  tasks: string | string[]
  noParallel?: boolean;
  noIncremental?: boolean;
  noDaemon?: boolean
}

export type initOption = {
  keepTemp?: boolean,
  sign?: boolean
}

/**
 * 用临时文件夹初始化一个临时测试工程模板
 *
 * @param from 要使用的模板测试用例工程
 * @param cb 要执行的测试逻辑方法，接收一个temp参数为临时文件夹的根目录
 * @param options
 * @param projectRootPathArg
 * @returns {Promise<void>}
 */
export async function initByProject(
  from: string,
  cb: (temp: string) => Promise<void>,
  options?: initOption,
  projectRootPathArg?: string) {
  const projectRootPath = projectRootPathArg === undefined ? appRoot() : projectRootPathArg;
  const initOption = {
    keepTemp: false,
    sign: true,
    ...options
  };
  await fs.ensureDir(resolve(projectRootPath!, 'test', 'temp'));
  const temp = await fs.mkdtemp(resolve(projectRootPath!, 'test', 'temp', 'temp_'));
  try {

    await fs.copy(resolve(projectRootPath!, 'test', 'cli', 'resource', 'application', from), temp);
    await Promise.all([runNpmInstall(temp)]);
    await cb(temp);
  } finally {
    if (!initOption.keepTemp) {
      await fs.remove(temp);
    }
  }
}

/**
 * 返回package的根目录
 *
 * @returns {string} package的根目录
 */
export function appRoot(dirname: string = __dirname) {
  while (!fs.existsSync(resolve(dirname, 'package.json'))) {
    dirname = resolve(dirname, '..');
  }
  return dirname;
}

/**
 * 执行项目的npm install
 *
 * @param {string} path
 * @returns {Promise<execa.ExecaChildProcess>}
 */
async function runNpmInstall(path: string): Promise<void> {
  const buildProfile = Json5Reader.getJson5Obj(resolve(path, 'build-profile.json5'));
  const srcPaths = [path, ...buildProfile.modules.map((unit: { [index: string]: string }) => {
    return resolve(path, unit['srcPath']);
  })];
  await Promise.all(srcPaths.map((srcPath: string) => {
    return execa.command('npm install', {
      cwd: srcPath
    });
  }));
}


/**
 * 初始化命令
 *
 * @param {hvigorOptions} options 传入命令参数
 * @returns {string[]} commands 生成命令行指令
 */
export function initExecuteCommand(options: hvigorOptions) {
  const commands: string[] = [];
  const {
    mode,
    module,
    log,
    require,
    version,
    v,
    sync,
    tasks,
    noParallel,
    noIncremental,
    noDaemon
  } = options;
  if (mode) {
    commands.push('-m');
    commands.push(mode);
  }
  if (module) {
    commands.push('-p');
    if (typeof module === 'string') {
      commands.push(`module=${module}`);
    } else {
      commands.push(`module=${module.join(',')}`);
    }
  }
  if (log) {
    commands.push(`-${log}`);
  } else {
    commands.push('-d');
  }
  if (require) {
    commands.push('--require');
    commands.push(require);
  }
  if (v) {
    commands.push('--version');
  }
  if (version) {
    commands.push('version');
  }
  if (sync) {
    commands.push('-s');
  }
  if (noParallel) {
    commands.push('--no-parallel');
  }
  if (noIncremental) {
    commands.push('--no-incremental');
  }
  if (noDaemon) {
    commands.push('--no-daemon');
  }
  if (typeof tasks === 'string') {
    commands.push(tasks);
  } else {
    commands.push(tasks.join(' '));
  }
  return commands;
}

/**
 * 传入命令和工程根目录，执行hvigor任务
 *
 * @param {string} path 工程根目录
 * @param {string[]} commands 执行命令
 * @returns {Promise<execa.ExecaChildProcess>}
 */
export function runHvigor(path: string, commands: string[]): execa.ExecaChildProcess {
  const process = execa.node(require.resolve('@ohos/hvigor/bin/hvigor-simple.js'), commands, {
    cwd: path,
  });
  if (debugMode) {
    console.log('===================');
    console.log(process.stdout);
    console.log(process.stderr);
  }
  return process;
}

/**
 * 传入命令和工程根目录，执行hvigor任务
 *
 * @param {string} path 工程根目录
 * @param {string[]} commands 执行命令
 * @returns {Promise<string | undefined>}
 */
export async function runHvigorReturnResult(path: string, commands: string[]): Promise<string | undefined> {
  let result: string | undefined;
  try {
    await runHvigor(path, commands);
  } catch (e: any) {
    result = e.stack;
    if (debugMode) {
      console.log(result);
    }
  }
  return result;
}
